/**
 * Created by xujiawei on 2020-07-07 15:09:32
 */

import { LocalDataMng } from './../data/localData/LocalDataMng';
import { ConstData } from './../data/ConstData';
import { Loading } from './Loading';
import { broadcast, dsn, on } from '../platform/AppBridge';
import { isArray, isPlainObject, isString } from './TypeOf';
import { Alert } from './Alert';
import { Device } from './Device';
import { track } from './Reportor';
import { UI } from './UI';

export class Director {
    static scene: cc.Scene = null;  // 当前场景节点
    static sceneCanvas: cc.Node = null;  // 当前场景下的canvas节点
    static sceneComponent: cc.Component = null;  // 当前场景挂载的主脚本组件
    static uiRoot: cc.Node = null;  // 场景下的ui节点
    static sceneName: string = '';

    static isBackground: boolean = false;
    static toBackgroundOSTime: number = 0;

    static activePops: any[] = [];  // POP列表
    static persistRootNodeList: any[]; // 常驻节点列表

    // 计算游戏时间使用
    static enterGameTime: number = 0;
    static backgroundDuration: number = 0;

    static EventType: any = {
        ALL_SINGLE_POP_CLOSE: 'ALL_SINGLE_POP_CLOSE',  // 所有独立的pop被关闭
    }

    // !!!游戏启动第一时间要调用初始化
    static init(initComponent?: any) {
        // 首次进入场景没有走loadSceen导致取不到canvas
        this.sceneCanvas = cc.director.getScene().getChildByName("Canvas") || null;
        this.uiRoot = this.sceneCanvas || null;  // 多摄像机的情况下ui节点可能不能直接加到canvas上

        this.enterGameTime = Date.now();
        this.backgroundDuration = 0;

        // 前后台事件处理
        cc.game.on(cc.game.EVENT_HIDE, this.onEventHide, this);
        cc.game.on(cc.game.EVENT_SHOW, this.onEventShow, this);

        // 微信小游戏事件处理
        if (cc.sys.platform == cc.sys.WECHAT_GAME) {
            // @ts-ignore
            wx.onShow(this.onWXGShow.bind(this));
            // @ts-ignore
            wx.onHide(this.onWXGHide.bind(this));
            // wx.exitMiniProgram({
            //     success: function (res) {
            //         cc.log("wx.exitMiniProgram-success:", res);
            //     },
            //     fail: function (res) {
            //         cc.log("wx.exitMiniProgram-fail:", res);
            //     }
            // })
        }

        // 键盘事件
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);

        // Canvas渲染事件(截屏)
        cc.director.on(cc.Director.EVENT_AFTER_DRAW, this.onAfterDraw, this);

        // 设置屏幕旋转(H5)
        cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);

        // 设置屏幕适配
        // this.initResolutionPolicy();
        // this.setSceneResolution(initComponent);

        // 屏幕改变回调
        cc.view.setResizeCallback(function () {
            cc.log('[Director]', 'setResizeCallback');
            // this.initResolutionPolicy();
            // this.setSceneResolution(this.getSceneComponent());
        }.bind(this));

        on('broadcase', this.onBroadcast);
        on('goback', () => {
            Alert.show({
                okText: '再想想',
                cancleCb: () => {
                    cc.game.end();
                },
                cancleText: '确定',
                text: '确定退出游戏嘛？'
            });
        });
    }

    static onEventHide() {
        if (!this.isBackground) {

            this.isBackground = true;

            // 进入后台的时间
            this.toBackgroundOSTime = Date.now();
            cc.log('[Director]', '进入后台:', this.toBackgroundOSTime);

            // zc.audio.pauseAll();
            // 游戏逻辑处理
            LocalDataMng.saveDataToLocal();
        }
    }

    static onEventShow() {
        if (this.isBackground) {

            this.isBackground = false;

            const toForegroundOSTime = Date.now();
            const interval = toForegroundOSTime - this.toBackgroundOSTime;
            cc.log('[Director]', '进入前台-interval:', interval);
            this.backgroundDuration += interval;
            cc.log('[Director]', '进入后台总时间:', this.backgroundDuration);

            // zc.timer.reduceCDAll(interval);

            // zc.audio.resumeAll();
        }
    }

    // 微信小游戏show
    static onWXGShow(res) {
        cc.log('[Director]', 'onWXGShow', res);
    }

    // 微信小游戏hide
    static onWXGHide(res) {
        cc.log('[Director]', 'onWXGHide', res);
    }

    static onKeyDown(event: cc.Event.EventKeyboard) {
        cc.log('[Director]', 'onKeyDown', event.keyCode);
        switch (event.keyCode) {
            case cc.macro.KEY.back:
                cc.log('[Director]', "on key back down, keyCode: ", event.keyCode);
        }
    }

    // 渲染回调
    static onAfterDraw() {

    }

    // 隐藏websplash
    static hideWebSplash() {
        if (cc.sys.isBrowser) {
            setTimeout(() => {
                let splash = document.getElementById('splash');
                if (splash) {
                    splash.style.display = 'none';
                }
            }, 100);
        }
    }

    static onBroadcast(data: any) {
        cc.log('[Direct]', '收到app广播', data);
        const { list } = data || {};
        isArray(list) && list.forEach(item => {
            if (!isPlainObject(item) || !isString(item.key) || (item.dsn === dsn)) {
                return;
            }

            const { key, data } = item;
            switch (key) {
                case 'user.login':
                    //   userLoginData.onLoginSuccess(data, 'app');
                    break;

                case 'user.logout':
                    track({
                        action: 'game_kickout',
                        game_duration: this.getGameDuration()
                    });
                    Alert.show({
                        text: '当前账号已经在别的设备登陆，请重新登录!',
                        okCb: () => {
                            cc.game.end();
                        },
                        okText: '确定'
                    });
                    //   userLoginData.onLogoutSuccess();
                    //   ui.setLoadingState(1);  // Loading 打底，防止客户端切换视图过程中看到白屏
                    break;

                case 'user.info':
                    //   userInfoData.onUserInfoDateUpdate(data, true);
                    break;

                // FIXME: 测试用
                case 'test.openDialog':
                    //   isPlainObject(data) && isArray(data.buttons) && callApp({
                    //     action: 'openDialog',
                    //     data,
                    //   });
                    break;

                // FIXME: 测试用
                case 'test.requestBroadcast':
                    //   broadcast({
                    //     key: 'test.responseBroadcast',
                    //     data,
                    //   });
                    break;

                default:
            }
        });
    }

    // 获取游戏总时间（去除后台时间)
    static getGameDuration() {
        const cur = Date.now();
        const all = cur - this.enterGameTime - this.backgroundDuration;
        cc.log('[Director]', `游戏总时间:${all}`);
        return all;
    }

    // 获取游戏启动时间消耗
    static getBootTimeConsumed() {
        let consumed = 0;
        // @ts-ignore
        if (window.__gameBootTime) {
            // @ts-ignore
            consumed = Date.now() - window.__gameBootTime;
        }
        return consumed;
    }

    static preloadScene(sceneName: string, onProgress?: (completedCount: number, totalCount: number, item: any) => void, onLoaded?: (error: Error) => void): void {
        cc.director.preloadScene(sceneName, onProgress, onLoaded);
    }

    // 加载Scene
    static loadScene(sceneName: string, params?: any, onLaunched?: (scene: cc.Scene, canvas: cc.Node, cmp: cc.Component) => void): any {
        // 清除所有POP
        this.closeAllPops();

        window[this.sceneName + 'Scene'] = null;

        cc.director.loadScene(sceneName, function () {
            cc.log('[Director]', 'loadScene:', sceneName);

            this.scene = cc.director.getScene();
            this.sceneCanvas = this.scene.getChildByName('Canvas');
            this.uiRoot = this.sceneCanvas.getChildByName("UIRoot") || this.sceneCanvas;
            this.sceneName = sceneName;
            this.sceneComponent = this.sceneCanvas.getComponent(sceneName + 'Scene');
            if (this.sceneComponent) {
                this.sceneComponent.sceneName = sceneName + 'Scene';
                if (this.sceneComponent.init) {
                    this.sceneComponent.init(params);
                }
            }

            window[this.sceneName + 'Scene'] = this.sceneComponent;

            if (onLaunched) {
                onLaunched(this.scene, this.sceneCanvas, this.sceneComponent);
            }

            // 解决IOS web下不播放音频的问题
            // zc.audio.showIOSWebMask();

        }.bind(this));
    }

    // 获取当前Scene名字
    static getSceneName() {
        return this.sceneName ? this.sceneName : '';
    }

    // 获取Scene脚本
    static getSceneComponent() {
        return this.sceneComponent;
    }

    // 获取Scene
    static getScene() {
        return this.scene;
    }

    // 获取Scene Canvas
    static getSceneCanvas() {
        return this.sceneCanvas;
    }

    // 获取ui根节点
    static getUiRoot() {
        return this.uiRoot;
    }

    // 加载Prefab
    static createPopWithLoader(popName: string, params?: any, loader?: cc.AssetManager.Bundle, prefab?: cc.Prefab) {
        if (!loader) {
            loader = cc.resources;
        }
        const beginTime = Date.now();
        params = params || {};

        let componentName = '';
        const popNameSpArr = popName.split('/');
        if (popNameSpArr.length > 0) {
            componentName = popNameSpArr[popNameSpArr.length - 1];
        }

        cc.log('[Director]', 'createPop:' + popName, componentName);
        if (this.isPopActive(popName)) {
            cc.log('[Director]', '当前POP已存在:' + popName);
            return
        }

        Loading.show(popName, 0.5);
        let initFunc = function (prefab: cc.Prefab) {
            const beginTime2 = Date.now();
            let popNode: cc.Node = cc.instantiate(prefab);
            popNode.position = cc.v3(0, 0, 0);
            popNode.zIndex = this.getTopPopZIndex() + 10;

            UI.pauseNodeTouchEvent(cc.Canvas.instance.node, true);

            popNode.parent = this.uiRoot;
            Loading.hide(popName);
            // 存到列表
            let popData = { popName: popName, popNode: popNode, popBase: null, popComponent: null };
            this.activePops.push(popData);
            // POPBase
            let popBase = popNode.getComponent('PopBase');
            if (!popBase) {
                cc.error('PopBase not find!');
                return;
            }
            popData.popBase = popBase; // 存入数据

            popBase.initBase(params, popName);
            popData.popComponent = popBase.component;
            const endTime = Date.now();
            cc.log('[Director]', '总耗时: ', endTime - beginTime, 'ms');
            cc.log('[Director]', '实例化和添加耗时: ', endTime - beginTime2, 'ms');
        }.bind(this);

        // 如果传入了prefab，直接使用
        if (prefab) {
            initFunc(prefab);
        } else {
            // 加载 Prefab
            loader.load(popName, cc.Prefab, null, function (err, prefab) {
                if (err) {
                    cc.log('[Director]', popName + '加载失败', err);
                    // zc.ui.loading.hide('pop');
                    return;
                }

                initFunc(prefab);
            }.bind(this));
        }
    }

    // 加载Prefab
    static createPop(popName: string, params?: any, prefab?: cc.Prefab) {
        this.createPopWithLoader(popName, params, cc.resources, prefab);
    }

    // 获取最上层的POP
    static getTopPopData(_topIndex?: number) {
        let topIndex = _topIndex ? _topIndex : 1;
        return this.activePops[this.activePops.length - topIndex];
    }

    static getTopPopZIndex() {
        let topPop = this.getTopPopData();
        if (topPop) {
            return topPop.popNode.zIndex;
        }
        return ConstData.ZIndex.POP_BASE;
    }

    // 获取POP数据
    static getPopData(popName) {
        for (const i in this.activePops) {
            const popData = this.activePops[i];
            if (popData.popName == popName) {
                return popData;
            }
        }
    }

    // 获取POP
    static getPop(popName) {
        let popData = this.getPopData(popName);
        if (popData) {
            return popData.popComponent;
        }
    }

    // POP是否存在
    static isPopActive(popName: string) {
        if (this.getPopData(popName)) {
            return true;
        }
        return false;
    }


    static getActivePops() {
        return this.activePops;
    }

    // 关闭Prefab
    static closePop(popName: string) {
        cc.log('[Director]', 'closePop:' + popName);
        const popData = this.getPopData(popName);
        if (popData) {
            for (let i: number = 0; i < this.activePops.length; i++) {
                const _popData = this.activePops[i];
                if (popData == _popData) {
                    this.activePops.splice(i, 1);
                    break;
                }
            }

            UI.resumeNodeTouchEvent(cc.Canvas.instance.node, true);
            // POPBase
            let popBase = popData.popBase;
            popBase.cleanBase();

            // 当所有独立的POP被关闭
            if (this.activePops.length == 0 && !popBase.onClosedCallback) {
                cc.director.emit(Director.EventType.ALL_SINGLE_POP_CLOSE);
            }

        }
    }

    static closeAllPops() {
        while (this.activePops.length > 0) {
            let idx = this.activePops.length - 1;
            let popData = this.activePops[idx];

            let popName = popData.popName;
            cc.log('closeAllPops:' + popName);

            this.activePops.splice(idx, 1);

            let popBase = popData.popBase;
            popBase.cleanBase();
        }

        this.activePops = [];
    }

    // 常驻节点数据
    static addPersistRootNode(node: cc.Node) {
        cc.game.addPersistRootNode(node);
        this.persistRootNodeList.push(node);
    }

    // 清理常驻节点数据
    static cleanPersistRootNode() {
        for (const index in this.persistRootNodeList) {
            const node = this.persistRootNodeList[index];
            cc.game.removePersistRootNode(node);
        }
    }
}